package com.collabscm.waf.util;

import java.util.Date;

import com.collabscm.waf.solution.auth.UserInfo;

/**
 * 运行时上下文，提供对运行环境使用到各种内容的各种方法。
 * @author Zeng Raoxing
 */
public class RuntimeContext {
	/**
	 * 线程请求时间
	 */
	private static ThreadLocal<Date> threadTime = new ThreadLocal<Date>();
	/**
	 * 线程中的用户信息
	 */
	private static ThreadLocal<UserInfo> threadUserInfo = new ThreadLocal<UserInfo>();
	/**
	 * 是否本线程需要在线调试
	 */
	private static ThreadLocal<Boolean> threadTrace = new ThreadLocal<Boolean>();
	/**
	 * 当前线程的语言类型
	 */
	private static ThreadLocal<String> threadLang = new ThreadLocal<String>();
	/**
	 * 当前运行模式，false代表目前是开发模式，true代表目前是生产模式。
	 */
	public static final boolean PRODUCT_MODE = false;
	
	public static final Integer FORM_REQUEST = 0;
	public static final Integer AJAX_REQUEST = 1;
	public static final Integer WS_REQUEST = 2;
	/**
	 * 当前请求类型，0: Form请求; 1: Ajax请求; 2: WebService请求
	 */
	public static ThreadLocal<Integer> threadRequestType = new ThreadLocal<Integer>();
	
	/**
	 * 得到当前操作时间，放置在一次交易中多次创建Date对象。
	 * 一是导致事件可能存在一定差异，二是将多次实例化一个对象。
	 */
	public static Date getCurrentDate() {
		Date current = threadTime.get();
		if(current == null) {
			current = new Date();
			threadTime.set(current);
		}
		return current;
	}
	
	/**
	 * 得到当前的操作的用户信息
	 */
	public static UserInfo getCurrentUserInfo() {
		//注意用户信息是在
		return threadUserInfo.get();
	}
	
	/**
	 * 判断本线程是否为在线追踪
	 */
	public static boolean isTraceEnabled() {
		return threadTrace.get() == Boolean.TRUE;
	}
	
	/**
	 * 得到当前的语言
	 */
	public static String getLanguage() {
		return threadLang.get();
	}
	
	/**
	 * 得到当前请求是什么类型
	 */
	public static Integer getRequestType() {
		return threadRequestType.get();
	}
	
	/**
	 * 清除一个线程中残留的内容，为了防止某些Server对ThreadLocal处理上的Bug。
	 */
	public static void clearThread() {
		threadTime.remove();
		threadUserInfo.remove();
		threadTrace.remove();
		threadLang.remove();
	}
	
	/**
	 * 应用上下文的设置器，用于对环境内容的具体设置，例如：对应用户信息仅能是特定的信息地方设置，
	 * 不能所有地方都能设置，因此采用内部类的方式屏蔽不需要暴露给外部随意调用的方法。
	 * 
	 * @author Zeng Raoxing
	 */
	public static class Setter {
		/**
		 * UserInfo的设置方法
		 * @param userInfo
		 */
		protected void setUserInfo(UserInfo userInfo) {
			RuntimeContext.threadUserInfo.set(userInfo);
		}
		
		/**
		 * 设置当前线程为需要追踪
		 */
		protected void setTrace() {
			threadTrace.set(Boolean.TRUE);
		}
		
		/**
		 * 设置用户请求的语言
		 */
		protected void setLanguage(String language) {
			threadLang.set(language);
		}
	}

}
